package org.yray.sip.base;

import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.util.StringUtils;
import org.yray.sip.constant.SipCodeEnum;

import java.io.BufferedReader;
import java.util.*;

@Slf4j
public class SipMsg{

    private Map<String,String> sipMap=new LinkedHashMap<>();
    private List<String> sdpList=new LinkedList<>();
    private String receiveIp;
    private int receivePort;
    private String firstRow;
    private boolean isBlank;
    private String clientIpPort;

    public String getLine() {
        return line;
    }

    public String getToPhone() {
        return toPhone;
    }

    //只有错误时才会有
    private SipCodeEnum sipCode;

    public Map<String, String> getSipMap() {
        return sipMap;
    }

    public void setSipMap(Map<String, String> sipMap) {
        this.sipMap = sipMap;
    }

    private String ext;
    private boolean needAuth;
    private String callId;
    private BufferedReader br;
    private String msg;
    private String line;
    private String toPhone;

    private SipMsg()
    {

    }
    public static SipMsg newSipMsg()
    {
        return new SipMsg();
    }
    public SipMsg msg(String msg)
    {
        this.msg=msg;
        return this;
    }
    public SipMsg ext(String ext)
    {
        this.ext=ext;
        return this;
    }
    public SipMsg toPhone(String toPhone)
    {
        this.toPhone=toPhone;
        return this;
    }

    public SipMsg line(String line)
    {
        this.line=line;
        return this;
    }
    public SipMsg bufferedReader(BufferedReader br)
    {
        this.br=br;
        return this;
    }
    public SipMsg callId(String callId)
    {
        this.callId=callId;
        return this;
    }
    public SipMsg sipCode(SipCodeEnum sipCode)
    {
        this.sipCode=sipCode;
        return this;
    }
    public SipMsg build()
    {
        try {
            if (br != null) {
                firstRow = this.br.readLine();
                if (StringUtils.isEmpty(firstRow)) {
                    isBlank = true;
                }
                br.lines().forEach(str -> {
                    readLine(str);
                });
                br.close();
            } else if (msg != null) {
                String[] lines = msg.split(MsgEle.LINE_SEPARATOR);
                firstRow = lines[0];
                for (int i = 1; i < lines.length; i++) {
                    readLine(lines[i]);
                }
            }
        }
        catch (Exception e)
        {
            log.error("built sip msg err:{}", ExceptionUtils.getStackTrace(e));
        }
        return this;
    }
    public boolean isNeedAuth() {
        return needAuth;
    }

    public void setNeedAuth(boolean needAuth) {
        this.needAuth = needAuth;
    }

    public String getExt() {
        return ext;
    }


    public String getClientIpPort() {
        return clientIpPort;
    }

    public void setClientIpPort(String clientIpPort) {
        this.clientIpPort = clientIpPort;
    }



    public void readLine(String str)
    {
        if(!StringUtils.isEmpty(str))
        {
            if(str.indexOf(MsgEle.AUTHORIZATION)>-1)
            {
                setNeedAuth(true);
            }
            int semicolonIndex=str.indexOf(MsgEle.ELE_SEPARATOR);
            int equalIndex=str.indexOf(MsgEle.AUTHORIZATION_ELE_KEY_SEPARATOR);
            //sip报文格式
            if((semicolonIndex>-1&&semicolonIndex<equalIndex)||(equalIndex==-1&&semicolonIndex>-1)) {
                sipMap.put(str.substring(0,semicolonIndex), str.substring(semicolonIndex+1));
            }
            //SDP报文格式
            else if((equalIndex>-1&&equalIndex<semicolonIndex)||semicolonIndex==-1)
            {
                sdpList.add(str);
            }
            else
            {
                sdpList.add(str);
                log.info("加入换行:{}",str);
            }
        }

        else {
            log.info("maybe is blank={}",str);
        }
    }

    public String getReceiveIp() {
        return receiveIp;
    }

    public void setReceiveIp(String receiveIp) {
        this.receiveIp = receiveIp;
    }

    public int getReceivePort() {
        return receivePort;
    }

    public void setReceivePort(int receivePort) {
        this.receivePort = receivePort;
    }

    @Override
    public String toString()
    {
        if(StringUtils.isEmpty(firstRow))
        {
            return MsgEle.LINE_SEPARATOR;
        }
        StringBuilder sb=new StringBuilder(firstRow).append(MsgEle.LINE_SEPARATOR);
        //sip最前面
        sipMap.forEach( (key,val)->{
            sb.append(key).append(MsgEle.ELE_SEPARATOR).append(val).append(MsgEle.LINE_SEPARATOR);
        });
        if(!CollectionUtil.isEmpty(sdpList))
        {
            sb.append(MsgEle.LINE_SEPARATOR);
            //sdp接最后面
            sdpList.forEach( (val)->{
                sb.append(val).append(MsgEle.LINE_SEPARATOR);
            });
        }
        sb.append("\r\n");
        return sb.toString();
    }

    public MsgType getMsgType()
    {
       return MsgType.getMsgType(firstRow);
    }

    public String getBranch()
    {
        String via=sipMap.get(MsgEle.VIA);
        return via.substring(via.lastIndexOf("=")+1);
    }
    public String getTag()
    {
        String from=sipMap.get(MsgEle.FROM);
        String[] strs= from.split(";");
        if(strs.length==2)
        {
            return strs[1].substring(strs[1].lastIndexOf("=")+1);
        }
        else {
            return "";
        }

    }
    public String getCallId()
    {
        if(StringUtils.isEmpty(callId))
        {
            callId= Optional.ofNullable(getMsgLine(MsgEle.CALL_ID)).map(String::trim).orElse(null);
        }
        return callId;
    }
    public List<String> getSdpList() {
        return sdpList;
    }

    public void setSdpList(List<String> sdpList) {
        this.sdpList = sdpList;
    }

    public String getMsgLine(String key)
    {
        return sipMap.get(key);
    }

    public OkType getOkType()
    {
        String cseq=sipMap.get(MsgEle.CSEQ);

        return OkType.getEnum(cseq.substring(cseq.lastIndexOf(' ')+1));
    }

    public SipCodeEnum getSipCode() {
        return sipCode;
    }

    public void setSipCode(SipCodeEnum sipCode) {
        this.sipCode = sipCode;
    }
}
